use std::{
    fmt::Arguments,
    fs::{File, OpenOptions},
    io::{Seek, SeekFrom, Write},
    sync::Mutex,
};

/// 记录日志信息
#[macro_export]
macro_rules! log_info {
    ($fmt:expr) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 2 {
                $crate::log::_write(format_args!($fmt), $crate::log::INFO_COLOR);
            }
        }
    };
    ($fmt:expr, $($args:tt)*) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 2 {
                $crate::log::_write(format_args!($fmt, $($args)*), $crate::log::INFO_COLOR);
            }
        }
    };
}
/// 记录警告信息
#[macro_export]
macro_rules! log_warning {
    ($fmt:expr) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 1 {
                $crate::log::_write(format_args!($fmt), $crate::log::WARNING_COLOR);
            }
        }
    };
    ($fmt:expr, $($args:tt)*) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 1 {
                $crate::log::_write(format_args!($fmt, $($args)*), $crate::log::WARNING_COLOR);
            }
        }
    };
}
/// 记录错误信息
#[macro_export]
macro_rules! log_error {
    ($fmt:expr) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 0 {
                $crate::log::_write(format_args!("{}\n{}", $fmt, std::backtrace::Backtrace::force_capture()), $crate::log::ERROR_COLOR);
            }
        }
    };
    ($fmt:expr, $($args:tt)*) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 0 {
                $crate::log::_write(format_args!(concat!($fmt,"\n{}"), $($args)*, std::backtrace::Backtrace::force_capture()), $crate::log::ERROR_COLOR);
            }
        }
    };
}
/// 记录事件信息
#[macro_export]
macro_rules! log_event {
    ($fmt:expr) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 0 {
                $crate::log::_write(format_args!($fmt), $crate::log::EVENT_COLOR);
            }
        }
    };
    ($fmt:expr, $($args:tt)*) => {
        unsafe {
            if $crate::log::LOG_LEVEL > 0 {
                $crate::log::_write(format_args!($fmt, $($args)*), $crate::log::EVENT_COLOR);
            }
        }
    };
}

/// 颜色
#[cfg(target_os = "windows")]
pub const INFO_COLOR: u16 = windows_sys::Win32::System::Console::FOREGROUND_INTENSITY
    | windows_sys::Win32::System::Console::FOREGROUND_BLUE
    | windows_sys::Win32::System::Console::FOREGROUND_GREEN
    | windows_sys::Win32::System::Console::FOREGROUND_RED;
#[cfg(target_os = "windows")]
pub const WARNING_COLOR: u16 = windows_sys::Win32::System::Console::FOREGROUND_GREEN | windows_sys::Win32::System::Console::FOREGROUND_RED;
#[cfg(target_os = "windows")]
pub const ERROR_COLOR: u16 = windows_sys::Win32::System::Console::FOREGROUND_INTENSITY | windows_sys::Win32::System::Console::FOREGROUND_RED;
#[cfg(target_os = "windows")]
pub const EVENT_COLOR: u16 = windows_sys::Win32::System::Console::FOREGROUND_INTENSITY | windows_sys::Win32::System::Console::FOREGROUND_GREEN;

#[cfg(target_os = "linux")]
pub const INFO_COLOR: u16 = 7;
#[cfg(target_os = "linux")]
pub const WARNING_COLOR: u16 = 3;
#[cfg(target_os = "linux")]
pub const ERROR_COLOR: u16 = 1;
#[cfg(target_os = "linux")]
pub const EVENT_COLOR: u16 = 2;

/// 日志记录等级
pub static mut LOG_LEVEL: u32 = 3; //if cfg!(debug_assertions) { 3 } else { 2 };
/// 线程安全日志文件
static mut LOG_FILE: Mutex<Option<File>> = Mutex::new(None);
/// 参数: (格式化数据，日志类型)
//#[inline(always)]
pub fn _write(record: Arguments<'_>, color: u16)
{
    unsafe {
        // 获取时间
        let time = crate::time::local_time();
        // 拼接输出内容
        let out = std::fmt::format(format_args!(
            "[{}年{}月{}日 {}:{:02}:{:02}] {}\n",
            time.year, time.month, time.day, time.hour, time.minute, time.second, record
        ));
        // 获取锁
        match LOG_FILE.lock()
        {
            Ok(mut opt) =>
            {
                // 输出到控制台
                #[cfg(target_os = "windows")]
                {
                    let handle = windows_sys::Win32::System::Console::GetStdHandle(windows_sys::Win32::System::Console::STD_OUTPUT_HANDLE);
                    //获取窗口缓冲区信息
                    let mut csbi_info: windows_sys::Win32::System::Console::CONSOLE_SCREEN_BUFFER_INFO = std::mem::zeroed();
                    windows_sys::Win32::System::Console::GetConsoleScreenBufferInfo(handle, &mut csbi_info as *mut windows_sys::Win32::System::Console::CONSOLE_SCREEN_BUFFER_INFO);
                    //获取初始定义的文本属性，即默认属性
                    let w_old_color_attrs = csbi_info.wAttributes;
                    windows_sys::Win32::System::Console::SetConsoleTextAttribute(handle, (w_old_color_attrs & 0xFFF0) | color);
                    print!("{}", out);
                    windows_sys::Win32::System::Console::SetConsoleTextAttribute(handle, w_old_color_attrs);
                }
                #[cfg(target_os = "linux")]
                {
                    print!("{}[3{}m{}{}[0m", 27 as char, color, out, 27 as char);
                }
                #[cfg(all(not(target_os = "windows"), not(target_os = "linux")))]
                {
                    print!("{}", out);
                }
                // 写到文件
                match (*opt).as_ref()
                {
                    Some(mut file) =>
                    {
                        if let Err(e) = file.write_all(out.as_bytes())
                        {
                            eprintln!("写日志到文件出错! {}", e);
                        }
                    }
                    None =>
                    {
                        match OpenOptions::new().read(true).write(true).create(true).open("log.txt")
                        {
                            Ok(mut file) =>
                            {
                                match file.seek(SeekFrom::End(0))
                                {
                                    Ok(_) =>
                                    {
                                        match file.write_all(out.as_bytes())
                                        {
                                            Ok(_) =>
                                            {
                                                *opt = Some(file);
                                            }
                                            Err(e) =>
                                            {
                                                eprintln!("写日志到文件出错! {}", e);
                                            }
                                        }
                                    }
                                    Err(e) =>
                                    {
                                        eprintln!("跳转到日志文件末尾出错! {}", e);
                                    }
                                }
                            }
                            Err(e) =>
                            {
                                eprintln!("打开日志文件出错! {}", e);
                            }
                        }
                    }
                }
            }
            Err(e) =>
            {
                eprintln!("获取日志锁出错! {}", e);
            }
        }
    }
}
